<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    function randomString() {
      return Math.random().toString(36).substr(3, 6)
        + new Date().getTime().toString(36)
    }

    // 手写call fn.call(this, a, b,c)
    Function.prototype.myCall = function (context) {

      if (typeof context === 'object' && typeof context !== null) {
        let args = []
        for (let i = 1; i < arguments.length; i++) {
          args.push(arguments[i])
        }
        let prop = randomString()
        context[prop] = this
        let res = eval('context[prop](' + args + ')')
        delete context[prop]
        return res
      }
    }

    // 手写apply
    Function.prototype.myApply = function (context) {

      if (typeof context === 'object' && context !== null) {
        let args = []
        for (let i = 0; i < arguments.length; i++) {
          args.push(arguments[1][i])
        }
        let prop = randomString()
        context[prop] = this

        let res = eval("context[prop](" + args + ")")
        return res
      }
    }

    // 3.手写bind
    Function.prototype.myBind = function () {
      let fn = this
      let args = Array.prototype.slice.call(arguments)
      let context = args.shift()

      return function () {
        console.log(args.concat(Array.prototype.slice.call(arguments)));
        return fn.apply(context, args.concat(Array.prototype.slice.call(arguments)))
      }
    }


    function add(a, b) {
      return a + b
    }

    console.log(add.myCall({}, 1, 2));
    console.log(add.myApply({}, [3, 4]));
    console.log(add.myBind({}, 3, 4)());

  </script>
</body>

</html>